package com.simple.util;

import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

public class OCRYouDaoUtil {
	
	public static String ocr(String img)
		throws Exception {
		Map<String, String> map = new HashMap<>();
//        String url = "http://vertifytest.youdao.com/ocr_formula";
		String url = "https://openapi.youdao.com/ocr_formula";
		String appKey = "30af076128561436";
        String appSecret = "RxXsSwfGcIAcj4o861vYjCWLMDZq1tDi";
		String detectType = "10011";
		String imageType = "1";
		String docType = "json";
		String salt = String.valueOf(System.currentTimeMillis());
		
		map.put("appKey", appKey);
		map.put("img", img);
		map.put("detectType", detectType);
		map.put("imageType", imageType);
		map.put("langType", "auto");
		map.put("salt", salt);
		map.put("curtime", String.valueOf(System.currentTimeMillis() / 1000));
		map.put("docType", docType);
		String sign = encrypt(appKey + getInput(img) + salt + map.get("curtime") + appSecret, null);
		// System.out.println(sign);
		map.put("sign", sign);
		return requestOCRForHttp(url, map);
	}
	
	/**
	 * 获得图片base64的input
	 * @param input
	 * @return
	 */
	private static String getInput(String input) {
		if (input == null)
			return null;
		String result = "";
		int len = input.length();
		if (len <= 20) {
			result = input;
		}
		else {
			String startStr = input.substring(0, 10);
			String endStr = input.substring(len - 10, len);
			result = startStr + len + endStr;
		}
		return result;
	}
	
	private static String requestOCRForHttp(String url, Map<String, String> requestParams)
		throws Exception {
		String result = null;
		CloseableHttpClient httpClient = HttpClients.createDefault();
		/** HttpPost */
		HttpPost httpPost = new HttpPost(url);
		List<NameValuePair> params = new ArrayList<NameValuePair>();
		Iterator<Entry<String, String>> it = requestParams.entrySet().iterator();
		while (it.hasNext()) {
			Entry<String, String> en = it.next();
			String key = en.getKey();
			String value = en.getValue();
			if (value != null) {
				params.add(new BasicNameValuePair(key, value));
			}
		}
		httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
		/** HttpResponse */
		CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
		try {
			HttpEntity httpEntity = httpResponse.getEntity();
			result = EntityUtils.toString(httpEntity, "utf-8");
			EntityUtils.consume(httpEntity);
		}
		finally {
			try {
				if (httpResponse != null) {
					httpResponse.close();
				}
			}
			catch (IOException e) {
				System.out.println("## release resouce error ##" + e);
			}
		}
		return result;
	}
	
	/**
	 * 获取MessageDigest的加密结果
	 * @param strSrc
	 * @param encName
	 * @return
	 * @throws NoSuchAlgorithmException
	 */
	private static String encrypt(String strSrc, String encName)
		throws NoSuchAlgorithmException {
//        Preconditions.checkNotNull(strSrc);
		byte[] bt = strSrc.getBytes();
		if (encName == null || "".equals(encName)) {
			encName = "SHA-256";
		}
		MessageDigest md = MessageDigest.getInstance(encName);
		md.update(bt);
		return bytes2Hex(md.digest());
	}
	
	private static String bytes2Hex(byte[] bts) {
		String des = "";
		String tmp = null;
		for (int i = 0; i < bts.length; i++) {
			tmp = (Integer.toHexString(bts[i] & 0xFF));
			if (tmp.length() == 1) {
				des += "0";
			}
			des += tmp;
		}
		return des;
	}
	
	public static String getYDFormulaOcrString(JSONObject ocrJSONObj) {
		JSONArray regionArray = ocrJSONObj.getJSONArray("regions");
		if (regionArray == null || regionArray.size() == 0) {
			return null;
		}
		// 获取OCR识别结果
		StringBuilder ocrResultSB = new StringBuilder();
		int regionCount = regionArray.size();
		for (int i = 0; i < regionArray.size(); i++) { // 块
			JSONObject regionObj = (JSONObject)regionArray.get(i);
			JSONArray lineArray = regionObj.getJSONArray("lines");
			if (lineArray == null || lineArray.size() == 0) {
				continue;
			}
			int lineCount = lineArray.size();
			int shortFormulaAndTextCount = 0;
			StringBuilder lineSB = new StringBuilder();
			for (int j = 0; j < lineArray.size(); j++) { // 行
				JSONArray tmpArray = (JSONArray)lineArray.get(j);
				if (tmpArray == null || tmpArray.size() == 0) {
					continue;
				}
				for (int k = 0; k < tmpArray.size(); k++) {
					JSONObject obj = tmpArray.getJSONObject(k);
					String text = obj.getString("text");
					String type = obj.getString("type");
					if (type.equals("formula")) {
						text = text.replaceAll("si\\s*([\\\\^{])", "sin$1")
							.replaceAll("co\\s*([\\\\^{])", "cos$1")
							.replaceAll("\\{}", " ")
							.trim();
						while (text.endsWith("{")) {
							text = text.substring(0, text.length() - 1).trim();
						}
					}
					lineSB.append(text);
				}
				if (lineSB.toString().length() < 3) {
					shortFormulaAndTextCount++;
				}
			}
			double shortFormulaAndTextRatio = 1.0 * shortFormulaAndTextCount / lineCount;
			if (regionCount > 1 && shortFormulaAndTextRatio > 0.9) {
				continue;
			}
			ocrResultSB.append(lineSB);
			ocrResultSB.append(" ");
		}
		
		return ocrResultSB.toString().replaceAll("\\s+", " ").trim();
	}
}
